package com.aqie.arithmetic.sort;

import com.aqie.libs.StdOut;
import com.aqie.libs.StdRandom;

/**
 * 模板设计模式
 * 1. 单纯在父类 调用 子类重写父类的方法，最终只是会调用父类空方法
 * 2. 如果父类构造器调用了被子类重写的方法，且通过子类构造函数创建子类对象，调用了这个父类构造器（无论显示还是隐式），就会导致父类在构造时实际上调用的是子类覆盖的方法
 *   - 优点：通过继承相同的父类，初始化子类时，父类会调用不同子类的不同复写方法，从而实现多态性。
 *   - 缺点：如果在父类构造函数中调用被子类重写的方法，会导致子类重写的方法在子类构造器的所有代码之前执行，从而导致子类重写的方法访问不到子类实例变量的值，因为此时这些变量还没有被初始化。
 * 3. static 修饰方法属于类，不能给子类继承
 */
public abstract class SortTest {
    public SortTest() {
        // process(10);
    }

    public abstract void sort(Comparable[] a);

    // a[i] 比 a[i-1] 大
    protected static boolean less(Comparable v, Comparable w){
        return v.compareTo(w) < 0;
    }

    protected static void exch(Comparable[] a, int i, int j){
        Comparable t = a[i];
        a[i] = a[j];
        a[j] = t;
    }

    protected static void show(Comparable[] a){
        for (Comparable anA : a) {
            StdOut.print(anA + " ");
        }
        StdOut.println();
    }

    public static boolean isSorted(Comparable[] a){
        for (int i = 1; i < a.length; i++){
            if (less(a[i], a[i - 1])) return false;
        }
        return true;
    }

    public static  Double[] generateChaos(int N){
        Double a[] = new Double[N];
        for (int i = 0; i < N; i++){
            a[i] = StdRandom.uniform();
        }
        return a;
    }

    public final void process(int N){
        Double[] chaos = generateChaos(N);
        show(chaos);
        StdOut.println(isSorted(chaos));
        sort(chaos);
        show(chaos);
        StdOut.println(isSorted(chaos));

    }
}
